/**
 * @FileName: LoginService.java
 * @Author
 * @Description:
 * @Date 2016年1月4日 下午1:25:04
 * @CopyRight ZTE Corporation
 */
package cn.hpclub.server.service;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;

import cn.hpclub.server.constant.ClientApiConstant;
import cn.hpclub.server.constant.Constant;
import cn.hpclub.server.model.MemberOrg;
import cn.hpclub.server.model.MemberWhite;
import cn.hpclub.server.model.Organization;
import cn.hpclub.server.model.SysCodeType;
import cn.hpclub.server.util.DESCrypto;
import cn.hpclub.server.util.HttpUtil;
import cn.hpclub.server.util.InterfaceUtil;
import cn.hpclub.server.util.ResultCode;
import cn.hpclub.server.util.SystemConfigUtil;

public class LoginService{
    private static final String GROUP_ID         = "group_id";
    private static final String REGION_ID        = "regionId";
    private static final String RES_CODE_SUCCESS = "0000000";

    private static Logger       log              = LoggerFactory.getLogger(LoginService.class);

    public String               username         = "";
    public String               password         = "";
    public boolean              isDesPwd         = false;
    public MemberOrg            member           = null;
    private String              CMCC_HOST_PREFIX = SystemConfigUtil.getSystemConfig().getCmccHostPrefix();
    private String              ESB_HOST_PREFIX  = SystemConfigUtil.getSystemConfig().getEsbHostPrefix();
    private String              TOKEN            = "";

    public LoginService(String username, String password, boolean ptag){
        this.username = username;
        this.password = password;
        this.isDesPwd = ptag;
    }

    public ResultCode validate(){
        member = MemberOrg.dao.getActiveMemberbyUserName(username);
        if(member == null){
            return ResultCode.USER_NOT_EXIST;
        }

        // DES获取到原始密码
        if(isDesPwd){
            try{
                this.password = java.net.URLDecoder.decode(
                                                           DESCrypto.decrypt(password,
                                                                             ClientApiConstant.CONSTANT_DES_KEY),
                                                           ClientApiConstant.ENCODING);
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }

        String md5Passwd = DigestUtils.md5Hex(password);

        if(!(member.get("password").equals(md5Passwd))){
            return ResultCode.PASSWD_ERROR;
        }
        return ResultCode.SUCCESS;
    }

    public JSONObject getData(String token) throws Exception{
        TOKEN = token;// 将生成的token保存下来，后面接口直接使用
        if(member == null){
            member = MemberOrg.dao.getActiveMemberbyUserName(username);
        }
        JSONObject jo = new JSONObject();
        List<Record> list = SysCodeType.dao.getCodeValueByTypeCode("RXSBKG");
        if(list != null && list.size() > 0){
            Record record = list.get(0);
            String value = record.getStr("value");
            jo.put(ClientApiConstant.Key.FACE_CHECK, value);
        }
        jo.put(ClientApiConstant.Key.MONTH_SUMMARY, new JSONArray());
        int orgId = member.getInt(MemberOrg.ORG_ID);
        jo.put(ClientApiConstant.Key.ID, orgId);
        jo.put(ClientApiConstant.Key.STOREMASTERID, member.getInt(MemberOrg.ID));
        jo.put(ClientApiConstant.Key.NAME, member.getStr(MemberOrg.NAME));
        jo.put(ClientApiConstant.Key.STORE_NAME, Organization.dao.getOrgNameByOrgId(orgId));

        jo.put(ClientApiConstant.Key.STORE_LOGO,
               SystemConfigUtil.getSystemConfig().getHostPrefix() + "/upload/file/default_head_img.png");

        String weixin = member.getStr(MemberOrg.WEIXIN);
        jo.put(ClientApiConstant.Key.WEIXIN_NUM, weixin == null ? "" : weixin);
        jo.put(ClientApiConstant.Key.TOKEN, token);

        // 店长:1，店员:2
        int memberType = member.getInt(MemberOrg.MEMBER_TYPE);
        jo.put(ClientApiConstant.Key.IDENTITY_ID, memberType == 1 ? 1 : 2);

        String channelCode = Organization.dao.getNumCodeById(orgId);
        jo.put(ClientApiConstant.Key.CHANNEL_ID, channelCode);

        String empCode = member.getStr(MemberOrg.EMP_CODE);
        if(StrKit.isBlank(empCode)){
            throw new EmpCodeIsEmptyException("EmpCode is Empty. deny login.");
        }
        String mobile = member.getStr(MemberOrg.MOBILE);
        /* 构建CMCC参数 */
        jo.put("CmccParam", getCmccParam(orgId, empCode, mobile));

        putExtralUnsedValues(jo);

        return jo;
    }

    /**
     * @Title: putExtralUnsedValues
     * @Description:以下为暂时没有用到的参数，为客户端正常运行，暂时保留
     * @param jo
     *            JSONObject void
     */
    private void putExtralUnsedValues(JSONObject jo){
        jo.put(ClientApiConstant.Key.STOREMASTERGUID, "746ec60e2a674076a9a34bd41dd639e3");
        jo.put(ClientApiConstant.Key.THEME_ID, 0);
        jo.put(ClientApiConstant.Key.OTHER_CONTACTS, "");
        jo.put(ClientApiConstant.Key.OPERATING_TIME, 2);

        // 店铺配置
        jo.put(ClientApiConstant.Key.IS_SHOW_PHONENO, 2);
        jo.put(ClientApiConstant.Key.STORE_URL, "http://yyth5.vpclub.cn/dzg/ztewd/10204535.html");

        // 店铺等级
        jo.put(ClientApiConstant.Key.LEVEL_NO, 0);
        jo.put(ClientApiConstant.Key.LEVEL_NAME, "初级");

        // 销售目标等
        jo.put(ClientApiConstant.Key.SALE_AMOUNT, 0);
        jo.put(ClientApiConstant.Key.NEXT_LEVEL_SALE_AMOUNT, 0);
        jo.put(ClientApiConstant.Key.DIFFER_NEXT_LEVEL_SALE_AMOUNT, 0);

        // 我的排名
        jo.put(ClientApiConstant.Key.MY_ORDER, 0);
        jo.put(ClientApiConstant.Key.MY_ORDER_RATE, "0.00%");

        // 店铺排名
        jo.put(ClientApiConstant.Key.STORES_NUMBER, 6650);
        // 总收入，利润
        jo.put(ClientApiConstant.Key.TOTAL, 6650);
        jo.put(ClientApiConstant.Key.PROFIT, 0);

        // 联系方式
        jo.put(ClientApiConstant.Key.IM_ACCOUNT, "");
        jo.put(ClientApiConstant.Key.IM_PASSWORD, "");
        jo.put(ClientApiConstant.Key.VOIP_ACCOUNT, "");
        jo.put(ClientApiConstant.Key.VOIP_PASSWORD, "");
        jo.put(ClientApiConstant.Key.BANK_BINDED, "false");

        jo.put(ClientApiConstant.Key.BUYER_PHONE, "");
        jo.put(ClientApiConstant.Key.BUYER_TOKEN, "");
        jo.put(ClientApiConstant.Key.BUYER_BIND_STOREID, 0);

        jo.put(ClientApiConstant.Key.JPUSH_ID, "746ec60e2a674076a9a34bd41dd639e3");
        jo.put(ClientApiConstant.Key.JPUSH_GROUPID, "54470");
    }

    public boolean modifyPasswd(String newPasswd, boolean isDesPwd){
        // DES获取到原始密码
        if(isDesPwd){
            try{
                newPasswd = java.net.URLDecoder.decode(DESCrypto.decrypt(newPasswd, ClientApiConstant.CONSTANT_DES_KEY),
                                                       ClientApiConstant.ENCODING);
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }
        return MemberOrg.dao.modifyPasswd(username, DigestUtils.md5Hex(newPasswd));
    }

    // private JSONObject getCmccParam1(int orgId, String empCode, String
    // mobile) throws Exception{
    // try{
    // return getFromCmcc(orgId, empCode, mobile);
    // }
    // catch(IOException | JSONException e){
    // e.printStackTrace();
    // throw e;
    // }
    // catch(VerifyEmpCodeException | VerifyEmpCode9999Exception e){
    // return getForWhiteFromLocal(orgId, empCode, mobile, e);
    // }
    // }
    //
    // private JSONObject getForWhiteFromLocal(int orgId, String empCode, String
    // mobile, Exception e) throws Exception{
    // try{
    // if(MemberWhite.dao.existInWhiteList(mobile)){
    // return getFromLocal(orgId, empCode, mobile);
    // } else{
    // throw e;
    // }
    //
    // }
    // catch(Exception e1){
    // throw e;
    // }
    // }
    //
    // /**
    // * @Title: getFromLocal
    // * @Description:TODO
    // * @param orgId
    // * @param empCode
    // * @param mobile
    // * @param e
    // * @return
    // * @throws Exception
    // * JSONObject
    // */
    //
    // private JSONObject getFromLocal(int orgId, String empCode, String mobile)
    // throws Exception{
    // MemberOrg member = MemberOrg.dao.getActiveMemberbyUserName(username);
    // MemberWhite memberWhiteInfo = MemberWhite.dao.getMemberWhite(username);
    // if((member != null) && (memberWhiteInfo != null)){
    // JSONObject param = new JSONObject();
    // param.put("SystemSign", 11);
    // param.put("BCharge", 4001);
    // param.put("BChargeName", "CZ");
    // param.put("EmpCode", empCode);
    // param.put("CityChannelId", getCityChannelID(orgId));
    // param.put("ChannelId", memberWhiteInfo.getInt(MemberWhite.CHANNEL_ID));
    // param.put("CityCodeId", memberWhiteInfo.getInt(MemberWhite.CITYCODE_ID));
    // return param;
    // }
    // return null;
    // }

    private JSONObject getCmccParam(int orgId, String empCode, String mobile) throws Exception{
        try{
            return getFromCmcc(orgId, empCode, mobile);
        }
        catch(VerifyEmpCode9999Exception | VerifyEmpCodeException e){
            log.error("VerifyEmpCodeException | VerifyEmpCode9999Exception,to check white list:" + mobile);
            return getForWhiteFromCmcc(orgId, empCode, mobile, e);
        }
    }

    /**
     * @Title: getForWhite
     * @Description:TODO
     * @param orgId
     * @param empCode
     * @param mobile
     * @param e
     * @return
     * @throws Exception
     *             JSONObject
     */

    private JSONObject getForWhiteFromCmcc(int orgId, String empCode, String mobile, Exception e) throws Exception{
        try{
            String cmccUser = MemberWhite.dao.getCmccUserIfExistInWhiteList(mobile);
            if(cmccUser != null){
                // System.out.println("white list cmcc user:" + cmccUser);
                if(MemberOrg.dao.isExistMemberOrg(cmccUser)){
                    return getFromCmcc(orgId, empCode, cmccUser);
                } else{
                    // System.out.println("cmcc is not exist,or deleted,or
                    // disabled");
                    throw e;
                }
            } else{
                // System.out.println("user not in white list");
                throw e;
            }

        }
        catch(Exception e1){
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * @Title: getCmccParam
     * @Description:获取CmmcParam
     * @param orgID
     *            当前用户所属机构ID
     * @param empCode
     *            当前用户工号
     * @param mobile
     *            手机号
     * @return JSONObject
     * @throws IOException
     *             构建Cmmc参数异常
     * @throws VerifyEmpCodeException
     * @throws JSONException
     * @throws VerifyEmpCode9999Exception
     */
    private JSONObject getFromCmcc(int orgID, String empCode, String mobile)
            throws IOException, JSONException, VerifyEmpCodeException, VerifyEmpCode9999Exception{
        Map<String, String> map = getCityCodeIdFromRzl(mobile, empCode);
        String groupId = map.get(GROUP_ID);
        String channelID = Organization.dao.getNumCodeById(orgID);
        verifyChannelId(empCode, channelID, groupId);

        /**
         * 此处暂时不开启工号验证，否则大掌柜白名单会无法登陆
         */
        // verifyEmpCode(empCode,mobile,TOKEN,map.get(REGION_ID));

        JSONObject param = new JSONObject();
        param.put("SystemSign", 11);
        param.put("BCharge", 4001);
        param.put("BChargeName", "CZ");
        param.put("EmpCode", empCode);

        // 人员地市级所对应的渠道编码，来自DB
        param.put("CityChannelId", getCityChannelID(orgID));
        // 人员所对应的机构的渠道编码NumCode。取自DPR，保证最新。
        param.put("ChannelId", map.get(GROUP_ID));
        // 地市编码，取自DPR，保证最新。
        param.put("CityCodeId", map.get(REGION_ID));
        return param;
    }

    /**
     * @Title: verifyChannelId
     * @Description:校验服务器存储的channelID,如果为空，则不允许用户登录
     * @param empCode
     *            工号
     * @param channelID
     *            机构渠道编码
     * @param groupId
     *            中转服务器返回渠道编码
     * @throws VerifyEmpCode9999Exception
     *             void
     */
    private void verifyChannelId(String empCode, String channelID, String groupId) throws VerifyEmpCode9999Exception{
        if(StrKit.isBlank(channelID)){
            log.error("error: groudId is empty. empCode=" + empCode + ",channelID=" + channelID);
            throw new VerifyEmpCode9999Exception("您的工号所关联的渠道不正确，请联系管理员");
        }
    }

    private void verifyEmpCode(String empCode, String phoneNumber, String token, String regionId)
            throws VerifyEmpCode9999Exception{
        String url = ESB_HOST_PREFIX + "sGetLogInfoByPhn1?token=" + token + "&regionId=" + regionId;
        String data = "{\"BODY\":{\"PHONE_NO\":\"" + phoneNumber + "\"}}";
        String resultString = HttpUtil.getHttpByPostBody(url, data);
        JSONObject jo = new JSONObject(resultString);
        if(jo.getJSONObject("ROOT").getLong("RETURN_CODE") == 0){
            String login_no = jo.getJSONObject("ROOT").getJSONObject("OUT_DATA").getJSONObject("LOGINMSG_LIST")
                    .getString("LOGIN_NO");
            if(!empCode.equals(login_no)){
                log.error("error: groudId is empty. empCode=" + empCode + ",channelID=" + empCode);
                throw new VerifyEmpCode9999Exception("您的账号关联的工号不存在于BOSS系统中，请联系管理员");
            }
        } else{
            throw new VerifyEmpCode9999Exception(jo.getJSONObject("ROOT").getString("DETAIL_MSG"));
        }
    }

    /**
     * @Title: getCityChannelID
     * @Description:获取 当前用户所属地市分公司渠道编码
     * @param orgID
     *            用户所属机构ID
     * @return String 渠道编码
     */
    private String getCityChannelID(int orgID){
        String numCode = "";
        String sql = InterfaceUtil.getCitySql(String.valueOf(orgID), "id, NumCode");
        Record record = Db.findFirst(sql);
        if(record != null){
            numCode = record.getStr("NumCode");
        }
        return numCode;
    }

    /**
     * @Title: getCityCodeIdFromRzl
     * @Description:通过睿智郎接口获取地市编码
     * @param mobile
     *            用户电话号码
     * @param empCode
     *            用户工号
     * @return
     * @throws IOException
     *             网络异常
     * @throws VerifyEmpCodeException
     *             服务器返回CityCodeId不存在异常 String
     * @throws VerifyEmpCode9999Exception
     */
    public Map<String, String> getCityCodeIdFromRzl(String mobile, String empCode)
            throws IOException, VerifyEmpCodeException, VerifyEmpCode9999Exception{
        // 登录获取归属地信息调用接口迁移（能力开放平台转到rpc）

        // String params = String.format("login_no=%s|phone_no=%s", empCode,
        // mobile);
        // String encrytParam = encrytParam(params);
        // String result = getResponseFromRzl(encrytParam);
        // return parseResultCityCode(result);

        String data = "{\"BODY\":{\"OLD_SERVER\":\"\",\"PHONE_NO\":\"" + mobile + "\"}}";
        String url = ESB_HOST_PREFIX + "sSmsQryScL?token=" + TOKEN;
        String result = HttpUtil.getHttpByPostBody(url, data);
        return parseResultCityCode(result);
    }

    /**
     * @Title: parseResult
     * @Description:睿智郎结果解析
     * @param result
     *            服务器返回结果 void
     * @throws VerifyEmpCodeException
     * @throws IOException
     * @throws VerifyEmpCode9999Exception
     */
    private Map<String, String> parseResultCityCode(String result)
            throws VerifyEmpCodeException, IOException, VerifyEmpCode9999Exception{
        if(null == result){
            throw new IOException("result is null.");
        }
        try{
            JSONObject jo = new JSONObject(result).getJSONObject("ROOT");
            long resCode = jo.getLong("RETURN_CODE");
            String resMsg = jo.getString("RETURN_MSG");
            if(resCode == 0){
                HashMap<String, String> map = new HashMap<String, String>(2);
                JSONObject outData = jo.getJSONObject("OUT_DATA");
                // String value = getValue(outData, "REGION_ID");
                int region_id = outData.getInt("REGION_ID");
                map.put(REGION_ID, String.valueOf(region_id));
                String groupId = getValue(outData, "GROUP_ID");
                map.put(GROUP_ID, groupId);
                return map;
            } else{
                String detailMsg = getDetailMsg(jo);
                String msg = StrKit.isBlank(detailMsg) == false ? detailMsg : resMsg;
                throw new VerifyEmpCode9999Exception(msg);
            }
        }
        catch(JSONException e){
            throw new VerifyEmpCodeException("parseResultCityCode error:" + result);
        }
    }

    private String getDetailMsg(JSONObject jo){
        try{
            String detailMsg = jo.getString("detailMsg");
            return detailMsg;
        }
        catch(JSONException e){
            return "";
        }
    }

    /**
     * @Title: getValue
     * @Description:JSON解析，获取key对应的value
     * @param outData
     * @param key
     * @return
     * @throws VerifyEmpCodeException
     *             String
     */
    private String getValue(JSONObject outData, String key) throws VerifyEmpCodeException{
        String value;
        value = outData.getString(key);
        // log.info(key + "=" + value);
        if(StrKit.isBlank(value)){
            throw new VerifyEmpCodeException("Transfer station response is error:" + key + "is empty.");
        }
        return value;
    }

    /**
     * @Title: getResponseFromRzl
     * @Description:获取当前用户所属地市代码（睿智朗接口提供）
     * @param encrytParam
     * @throws IOException
     * @throws Exception
     *             void
     */
    private String getResponseFromRzl(String encrytParam) throws IOException{
        HashMap<String, Object> hm = new HashMap<String, Object>();
        JSONObject o = new JSONObject(encrytParam);
        hm.put("rawStr", o.get("rawStr"));
        String result = HttpUtil.getHttpByPost(CMCC_HOST_PREFIX + Constant.Url.VERIFY_EMP_CODE, hm);
        return result;
    }

    /**
     * @Title: encrytParam
     * @Description:加密发送参数
     * @param param
     *            原参数
     * @throws Exception
     *             String 加密后参数
     */
    private String encrytParam(String param) throws IOException{
        HashMap<String, Object> hm = new HashMap<String, Object>();
        hm.put("rawStr", param);
        String rawStr = HttpUtil.getHttpByPost(CMCC_HOST_PREFIX + Constant.Url.ENCODE_URL, hm);
        return rawStr;
    }

    public static class VerifyEmpCodeException extends Exception{
        private static final long serialVersionUID = 5591311293470873089L;

        public VerifyEmpCodeException(String message){
            super(message);
        }
    }

    public static class EmpCodeIsEmptyException extends Exception{
        private static final long serialVersionUID = 6084550438298974211L;

        public EmpCodeIsEmptyException(String message){
            super(message);
        }
    }

    public static class VerifyEmpCode9999Exception extends Exception{
        private static final long serialVersionUID = -448511834338404129L;

        public VerifyEmpCode9999Exception(String message){
            super(message);
        }
    }

}
